*This is the Stata do-file for 
*Patrick J. Egan (patrick.egan@nyu.edu)
*"Centering LGBTQ+ Behavior in Political Science" (PS Symposium, 2024)
*last revised: November 22, 2024

*files (2) included in replication archive:

*ces2022.dta - CES dataset
*figure3.grec - Stata graphics editor recording file

*before running this do-file, copy these two files into the working directory that you set further below 


version 17
set more off
clear all

*this do-file uses Trenton D. Mize's "cleanplots" Stata graph scheme (https://www.trentonmize.com/software/cleanplots). It can be downloaded, installed  and set with the following commands:

net install cleanplots, from("https://tdmize.github.io/data/cleanplots") replace
set scheme cleanplots

*set working directory:

cd "your working directory"


*the following command will download the original dataset from the CES dataverse, copy it into your working directory, and and name it ces2022.dta; this dataset is also included directly with the replication file 

*copy "https://dataverse.harvard.edu/api/access/datafile/10140881" ces2022.dta, replace

use ces2022.dta, clear

*generate a frequency weight variable as an integer:

gen fpw = round(commonpostweight*1000)


*create lgbtq+ demographic variable:

recode sexuality (1=0) (2/5=1) (6=0), gen(q)
replace q = 1 if gender4==3
replace q = 1 if transgender==1
replace q = . if transgender==.


*political conservatism:

pca CC22_321_1- CC22_334h CC22_350a- CC22_355e [fw=fpw]

predict conserv_f if e(sample)
 

xtile conserv100 = conserv_f [pweight = commonpostweight], nquantiles(100)



*political engagement/knowledge:

recode TS_voterstatus (.=0), gen(registered_v)

recode TS_p2022 (2/6=1) (7=0) (.=0), gen(voted_primary)

recode TS_g2022 (2/6=1) (7=0) (.=0), gen(voted_general)

gen k_house = 0
replace k_house = 1 if CC22_310a==2

gen k_pres = 0
replace k_pres = 1 if CC22_340d >= CC22_340c
replace k_pres = 0 if CC22_340c ==8
replace k_pres = 0 if CC22_340d ==8

gen k_party = 0
replace k_party = 1 if CC22_340f >= CC22_340e
replace k_party = 0 if CC22_340e ==8
replace k_party = 0 if CC22_340f ==8


*gen version of newsint coded in right direction:

gen newsint_rc = newsint
recode newsint_rc (7=5)
replace newsint_rc = 6-newsint_rc


*generate engagement factor:

pca registered voted_primary voted_general CC22_430a_1 CC22_430a_2 CC22_430a_3 CC22_430a_4 CC22_430a_5 CC22_430a_6 k_pres k_party k_house newsint_rc [fw=fpw]

predict engage_f if e(sample)

xtile engage100 = engage_f  [pweight = commonpostweight], nquantiles(100)


*religiosity:

recode pew_churatd (7=6), gen(church01)
recode pew_prayer (8=7), gen(prayer01)

pca church01 prayer01 pew_religimp [fw=fpw]

predict religiosity_f

xtile relig100 = religiosity_f [pweight = commonpostweight], nquantiles(100)

replace relig100 = 100-relig100


*health:

pca CC22_309e CC22_309f [fw=fpw]
predict health_f


xtile health100 = health_f [pweight = commonpostweight], nquantiles(100)

replace health100 = 100-health100


*SES:

*create interval-level measure of income:

gen income_k = .

for num 1(1)16 \ any 5 15 25 35 45 55 65 75 90 110 135 175 225 300 425 750: replace income_k = Y if faminc_new==X

*create interval-level variable assessing how R would deal with emergency expense. R could choose any or all of these options; score of variable is adjusted according to how option reflects R's financial health:

/*
CC22_309dx_1		Put on credit card, pay it off in full at next statement +2
CC22_309dx_2		Put on credit card, pay it off over time +1
CC22_309dx_3		With the money currently in my checking/savings account or with cash +3
CC22_309dx_4		Using money from a bank loan or line of credit +1
CC22_309dx_5		By borrowing from a friend or family member 0
CC22_309dx_6 		Using a payday loan, deposit advance, or overdraft -1
CC22_309dx_7		By selling something -2
CC22_309dx_8		I wouldn't be able to pay for the expense right now -3
*/

gen emergency = 0

for num 1(1)8 \ any 2 1 3 1 0 -1 -2 -3: replace emergency = emergency + Y if CC22_309dx_X==1

	pca educ income_k emergency [fw=fpw]

	predict ses_f

	xtile ses100 = ses_f [pweight = commonpostweight], nquantiles(100)



*generate two factors for map in Figure 3:

factor conserv100 relig100 ses100 engage100 health100    [fw=fpw]


*produce table of factor loadings found in endnotes:

rotate


predict f1 f2

*convert into percentiles:

xtile f1_100 = f1 [pweight = commonpostweight], nquantiles(100)
xtile f2_100 = f2 [pweight = commonpostweight], nquantiles(100)



*designate complete cases and drop incomplete cases:
gen complete = 1
for any ses100 health100 relig100 engage100 conserv100 q race religpew pew_bornagain: replace complete = 0 if X==.

keep if complete==1

*generate table of Gender, Gender Identity and Sexual Orientation Among 2022 CES Respondents (Appendix Table A1)

*combine lesbians, gays:

recode sexuality (3=2) (4=3) (5=4) (6=5), gen(so_rc)
label def so_rc 1 "straight" 2 "lesbian/gay" 3 "bisexual" 4 "other" 5 "not stated"
label values so_rc so_rc

*make Table A1 in Online Appendix:

table gender4 so_rc transgender if complete ==1

*get counts of groups cited in text:

*count of all LGBTQ+ people: 

tab q if complete==1

*generate indicator variable for each lgbtq group:

for any lesbian gayman biwoman biman othersexuality nonbinary transgender: gen X01 = 0 

replace lesbian01 = 1 if so_rc==2 & gender4==2
replace gayman01 = 1 if so_rc==2 & gender4==1

replace biwoman01 = 1 if so_rc==3 & gender4==2
replace biman01 = 1 if so_rc==3 & gender4==1

replace othersexuality01 = 1 if so_rc==4

replace nonbinary01 = 1 if gender4==3

replace transgender01 = 1 if transgender==1


*Generate data for Table 1 in text:

for any lesbian gayman biwoman biman othersexuality transgender nonbinary : replace X01 = . if q==. 

*unweighted:

tab q 

for any lesbian gayman biwoman biman othersexuality transgender nonbinary : tab X01 if q==1 


*weighted:
svyset [pw=commonpostweight]
svy: tab q 


for any lesbian gayman biwoman biman othersexuality transgender nonbinary : svy: tab X01 if q==1, percent format(%8.1f)


*Figures

*set up new dataset for figures:

gen group = ""
gen g_conserv = .
gen g_engage = .
gen g_relig = .
gen g_health = .
gen g_ses = .
gen g_pct = .
gen g_f1 = .
gen g_f2 = .
gen order = .


local group "{bf:LGBTQ+} White Black "Hispanic/Latino" Asian Native Multiracial "Other race" Protestant Catholic Mormon/LDS Jewish Muslim "Agnostic/atheist" "Born again" "Not LGBTQ+" Non-binary "Gay man" Lesbian "Bisexual man" "Bisexual woman" Transgender "Other sexuality""

local cond `" "q==1" "race==1 & hispanic~=1" "race==2" "race==3|hispanic==1" "race==4" "race==5" "race==6" "race==5|race==7|race==8" "religpew==1" "religpew==2" "religpew==3" "religpew==5" "religpew==6"  "religpew==9|religpew==10" "pew_bornagain==1" "q==0" "gender4==3" "(sexuality==2|sexuality==3)&gender4==1" "(sexuality==2|sexuality==3)&gender4==2" "sexuality==4&gender4==1" "sexuality==4&gender4==2" "transgender==1" "sexuality==5"'


gen unit = 0
	
local n : word count `group'

forvalues i = 1/`n' {

	replace unit = 0
	
	local g: word `i' of `group'
	local a: word `i' of `cond'

	replace order = `i' in `i'
	replace group = "`g'" in `i'
		
	summ conserv100 if `a' [fw=fpw], d
	replace g_conserv = `r(mean)' in `i'
	
	summ engage100 if `a' [fw=fpw], d
	replace g_engage = `r(mean)' in `i'

	summ relig100 if `a' [fw=fpw], d
	replace g_relig = `r(mean)' in `i'
	
	summ health100 if `a' [fw=fpw], d
	replace g_health = `r(mean)' in `i'

	summ ses100 if `a' [fw=fpw], d
	replace g_ses = `r(mean)' in `i'
	
	summ f1_100 if `a' [fw=fpw], d
	replace g_f1 = `r(mean)' in `i'

	summ f2_100 if `a' [fw=fpw], d
	replace g_f2 = `r(mean)' in `i'

	replace unit = 1 if `a' 
	summ unit [fw=fpw], d
	replace g_pct = 100*`r(mean)' in `i'
	
	}


save ces2022.mod.dta, replace


keep group-g_pct g_f1 g_f2
keep in 1/23
gen order = _n
for any 1 2 3 4 5 6: gen xX= X




gen queer = 0
replace queer = 1 in 1
replace queer = 1 in 17/23

gen groups = 0
replace groups = 1 in 1/16


gen label = group



for any conserv engage relig health ses: gen pos_X = g_X



*Figure 1:

*make adjustments to lgbtq+ labels for legibility:

*political conservatism:

for any 21 19 23 22 \ any 28.5 27 25.5 24: replace pos_conserv = Y if order==X

*political engagement:

for any 19 20   23 \ any 55 53.5  49.5 : replace pos_engage = Y if order==X

*religiosity:

for any 22 18  20 21 23 \ any 43 41 36 34.5 33: replace pos_relig = Y if order==X

*health:

for any 22  23 \ any 44 34: replace pos_health = Y if order==X

*ses:

for any 18 21 23 22 17 \ any 56 44.5 43 41.5 39.7  : replace pos_ses = Y if order==X


sort order

twoway (scatter pos_conserv x1 in 17/23, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_engage x2 in 17/23, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_relig x3 in 17/23, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_health x4 in 17/23, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_ses x5 in 17/23, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_conserv x1 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter pos_engage x2 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter pos_relig x3 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter pos_health x4 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter pos_ses x5 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) , xlabel(1 `""political" "conservatism""' 2 `""political" "engagement""' 3 "religiosity" 4 "health" 5 "SES", labsize(small)) xscale(range(.5 5.5)) scheme(cleanplots) ylabel(10 "10th" 20 "20th" 30 "30th" 40 "40th" 50 "50th" 60 "60th" 70 "70th" 80 "80th" 90 "90th" ) legend(off) ytitle(national percentile) yline(50, lc(ltblue)) 

graph export Figure1.png, as(png) width(4000) replace

graph export Figure1.tif, as(tif) width(4000) replace



*Figure 2:

*make adjustments to labels for legibility:

*conservatism:

replace pos_conserv = 64.7 if order==15
replace pos_conserv = 56.5 if order==8
replace pos_conserv = 51.5 if order==16
replace pos_conserv = 46.7 if order==4



*engagement:

for any   2 9 11  8 16 10 7 15 5 6 4 3 \ any 55 54 53  49 47.75 46.5 45.25 44 42.75 41 39.25 38 : replace pos_engage  = Y if order == X

*religion:

for any 6 16 8 4  7 5 12 \ any 56 54.5 53 51.75  48.5 47 45.75: replace pos_relig  = Y if order == X

*health:

for any 12 10 13 11 15 9 16 5 3 2 8  6 4 14 7 \ any 65.25 64 62.75 61.5 60.25 59 57.75 56.5 55.25 54 52.75 51.5   50.25 49 47.5 : replace pos_health  = Y if order == X

*SES:

for any 11 10 2    16 9 8 3 4  15 7 \ any  56 54.75 53.5  52.25 51 47 41.5 40.3 45.5 44: replace pos_ses  = Y if order == X




sort order 

twoway (scatter pos_conserv x1 in 2/16, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_engage x2 in 2/16, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_relig x3 in 2/16, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_health x4 in 2/16, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter pos_ses x5 in 2/16, mlab(label) mlabpos(0) ms(none) mlabsize(vsmall) mlabc(black)) (scatter g_conserv x1 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter pos_engage x2 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter g_relig x3 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter g_health x4 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)) (scatter pos_ses x5 in 1, mlab(label) mlabpos(0) ms(none) mlabsize(small) mlabc(red)), xlabel(1 `""political" "conservatism""' 2 `""political" "engagement""' 3 "religiosity" 4 "health" 5 "SES", labsize(small)) xscale(range(.5 5.5)) scheme(cleanplots) ylabel(20 "20th" 30 "30th" 40 "40th" 50 "50th" 60 "60th" 70 "70th" 80 "80th") legend(off) ytitle(national percentile) yline(50, lc(ltblue)) 



graph export Figure2.png, as(png) width(4000) replace

graph export Figure2.tif, as(tif) width(4000) replace








*Figure 3:

*create marker label positions for map in Figure 3:

gen pos = 4
replace pos = 8 if order == 2
replace pos = 12 if order == 3
replace pos = 7 if order == 4
replace pos = 7 if order == 7
replace pos = 2 if order == 5
replace pos = 3 if order == 9
replace pos = 3 if order == 8
replace pos = 2 if order == 11
replace pos = 7 if order == 1
replace pos = 2 if order == 10


twoway (scatter g_f1 g_f2 [w=g_pct] in 1/15, ms(o) mfc(ltblue) mc(gs7)) (scatter g_f1 g_f2 in 2/15, ms(none) mlab(label) mlabvpos(pos) mlabc(black) mlabg(1.5)) (scatter g_f1 g_f2 in 1, ms(none) mlab(label) mlabvpos(pos) mlabc(red) mlabs(large)), aspect(.6) scheme(cleanplots) legend(off) xtitle(" " "{bf:conservatism/religiosity} (%ile)") ytitle("{bf:resources/political engagement} (%ile)") xline(50) yline(50) xlabel(10 "10th" 20 "20th" 30 "30th" 40 "40th" 50 "50th" 60 "60th" 70 "70th" 80 "80th" 90 "90th") ylabel(30 "30th" 40 "40th" 50 "50th" 60 "60th" 70 "70th") 

*do some manual editing of marker label positions using graph editor recording file figure3.grec, included in this replication archive:

graph play "figure3"

graph export Figure3.png, as(png) width(4000) replace

graph export Figure3.tif, as(tif) width(4000) replace





